package com.dy.yunying.biz.service.manage.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dy.yunying.api.constant.ChannelConstants;
import com.dy.yunying.api.constant.ChannelPackTypeEnum;
import com.dy.yunying.api.constant.VersionStatusEnum;
import com.dy.yunying.api.dto.ParentGamePackDto;
import com.dy.yunying.api.dto.SonGameBasePackDto;
import com.dy.yunying.api.dto.SonGameDto;
import com.dy.yunying.api.entity.GameVersionDO;
import com.dy.yunying.api.entity.ParentGameDO;
import com.dy.yunying.api.entity.ParentGameVersionDO;
import com.dy.yunying.api.req.GameChannelPackReq;
import com.dy.yunying.api.req.ParentGameVersionReq;
import com.dy.yunying.api.resp.ParentGameDataRes;
import com.dy.yunying.api.vo.ChannelManageVo;
import com.dy.yunying.api.vo.ParentGameVersionVO;
import com.dy.yunying.api.vo.WanGameVersionVO;
import com.dy.yunying.biz.dao.manage.ext.ParentGameVersionDOMapperExt;
import com.dy.yunying.biz.service.manage.*;
import com.dy.yunying.biz.utils.DateUtils;
import com.dy.yunying.biz.utils.OkHttpUtil;
import com.pig4cloud.pig.admin.api.entity.SysUser;
import com.pig4cloud.pig.admin.api.feign.RemoteUserService;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.exception.BusinessException;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 游戏版本
 *
 * @Author: hjl
 * @Date: 2020/7/21 13:52
 */
@Transactional
@Slf4j
@Service
public class ParentGameVersionServiceImpl implements ParentGameVersionService {

	@Autowired
	private ParentGameVersionDOMapperExt parentGameVersionDOMapper;

	@Autowired
	private GameVersionService gameVersionService;

	@Autowired
	private GameService gameService;

	@Autowired
	private ParentGameService parentGameService;

	@Autowired
	private GameChannelPackService gameChannelPackService;

	@Autowired
	private ChannelManageService channelManageService;

	@Autowired
	private RemoteUserService remoteUserService;

	@Value("${pack.pack_api_son_pack_update}")
	private String pack_api_son_pack_update;

	@Value("${pack.app_file_url_root}")
	private String app_file_url_root;


	@Override
	public IPage<ParentGameVersionVO> page(ParentGameVersionReq req) {
		IPage<ParentGameVersionVO> page = parentGameVersionDOMapper.page(req);

		if (page.getRecords() != null || page.getRecords().size() > 0) {

			R<List<SysUser>> r = remoteUserService.getUserList(SecurityConstants.FROM_IN);

			Map<String, String> map = new HashMap<>();
			if (r.getCode() == CommonConstants.SUCCESS) {
				List<SysUser> list = r.getData();
				map = list.stream().collect(Collectors.toMap(
						o -> {
							return String.valueOf(o.getUserId());
						}, SysUser::getRealName));
			}

			Map<String, String> finalMap = map;
			page.getRecords().forEach(data -> {

				String creator = data.getCreator();
				data.setCreatorName(finalMap.get(creator) == null ? creator : finalMap.get(creator));

				if (StringUtils.isNotBlank(data.getPath())) {
					data.setPath(app_file_url_root + data.getPath());
				}
			});
		}
		return page;
	}

	@Override
	public ParentGameVersionDO getByPK(Long versionId) {
		return parentGameVersionDOMapper.selectByPrimaryKey(versionId);
	}

	@Override
	public ParentGameVersionDO getLatestByGameId(Long gameId, Integer packType) {
		return parentGameVersionDOMapper.getLatestByGameId(gameId, packType);
	}

	@Override
	public List<ParentGameVersionDO> getPackTypeByGameId(Long gameId) {
		return parentGameVersionDOMapper.getPackTypeByGameId(gameId);
	}

	@Override
	public ParentGamePackDto getParentGamePackByPK(Long versionId) {
		return parentGameVersionDOMapper.getParentGamePackByPK(versionId);
	}

	/**
	 * 更新子游戏基础包
	 *
	 * @param parentGameVersionDO
	 */
	@Override
	public List<GameVersionDO> updateBasePack(ParentGameVersionDO parentGameVersionDO, Long sonGameId) {
		List<Long> gameIdList = new ArrayList<>();
		gameIdList.add(sonGameId);
		List<SonGameDto> sonGameList = gameService.selectDtoByPKs(gameIdList);
		return updateBasePack(parentGameVersionDO, sonGameList);
	}

	@Override
	public List<GameVersionDO> updateBasePack(ParentGameVersionDO parentGameVersionDO, List<SonGameDto> sonGameList) {
		List<GameVersionDO> gameVersionDOList = new ArrayList<>();
		try {
			if (parentGameVersionDO == null) {
				throw new BusinessException(11, "父游戏母包不存在");
			}
			if (CollectionUtils.isEmpty(sonGameList)) {
				throw new BusinessException(12, "子游戏不存在");
			}

			// 查询父游戏信息
			ParentGameDO parentGameDO = parentGameService.getByPK(parentGameVersionDO.getGameId());
			if (parentGameDO == null) {
				throw new BusinessException(13, "父游戏不存在");
			}

			// TODO 使用 Map<String, Object> 和 JSON.toJSONString() 会导致 签名不一致
			Map<String, String> params = new HashMap<>();
			params.put("versionId", String.valueOf(parentGameVersionDO.getVersionId()));
			params.put("versionCode", String.valueOf(parentGameVersionDO.getCode()));
			params.put("parentGamePath", parentGameVersionDO.getPath());
			params.put("parentGameStr", JSON.toJSONString(parentGameDO));
			params.put("sonGameListStr", JSON.toJSONString(sonGameList));

			log.info("调用网关接口, params：{}", JSON.toJSONString(params));
			String result = OkHttpUtil.doPostForm(pack_api_son_pack_update, params);
			log.info("调用网关接口,返回result:{}", result);

			if (StringUtils.isNotEmpty(result)) {
				JSONObject jo = JSON.parseObject(result);
				Integer code = jo.getInteger("code");
				if (code != null) {
					if (code == 0) {
						JSONObject date = jo.getJSONObject("data");
						JSONArray sonGameBasePackDtoList = date.getJSONArray("sonGameBasePackDtoList");
						if (sonGameBasePackDtoList == null || sonGameBasePackDtoList.isEmpty()) {
							log.error("生成子游戏基础包失败");
							throw new BusinessException(12, "生成子游戏基础包失败");
						}
						for (int i = 0; i < sonGameBasePackDtoList.size(); i++) {
							SonGameBasePackDto sonGameBasePackDto = sonGameBasePackDtoList.getObject(i, SonGameBasePackDto.class);
							sonGameBasePackDto.getGameId();

							GameVersionDO gameVersionDO = new GameVersionDO();
							gameVersionDO.setGameId(sonGameBasePackDto.getGameId());
							gameVersionDO.setPackType(parentGameVersionDO.getPackType());
							gameVersionDO.setPath(sonGameBasePackDto.getDecodePath());
							gameVersionDO.setCode(parentGameVersionDO.getCode());
							gameVersionDO.setName(parentGameVersionDO.getName());
							gameVersionDO.setContent(parentGameVersionDO.getContent());
							gameVersionDO.setRemark(parentGameVersionDO.getRemark());
							gameVersionDO.setSize(parentGameVersionDO.getSize());
							gameVersionDO = gameVersionService.save(gameVersionDO);

							gameVersionDOList.add(gameVersionDO);
						}
						return gameVersionDOList;
					} else {
						String msg = jo.getString("msg");
						log.error("生成渠道包失败, msg:{}", msg);
						throw new BusinessException(12, "msg");
					}
				} else {
					log.error("请求生成渠道包接口失败");
					throw new BusinessException(12, "请求生成渠道包接口失败");
				}
			}
		} catch (Exception e) {
			log.error("生成子游戏基础包失败", e);
			throw new BusinessException(1, "生成子游戏基础包失败");
		}
		log.error("生成子游戏基础包失败");
		throw new BusinessException(1, "生成子游戏基础包失败");
	}

	@Override
	public List<GameVersionDO> updateBasePack2(ParentGameVersionDO parentGameVersionDO, Long sonGameId) {
		List<Long> gameIdList = new ArrayList<>();
		gameIdList.add(sonGameId);
		List<SonGameDto> sonGameList = gameService.selectDtoByPKs(gameIdList);
		return updateBasePack2(parentGameVersionDO, sonGameList);
	}

	@Override
	public List<ParentGameVersionDO> selectListByPgId(List<ParentGameDataRes> pgIdList) {
		return parentGameVersionDOMapper.selectListByPgId(pgIdList);
	}

	@Override
	public List<GameVersionDO> updateBasePack2(ParentGameVersionDO parentGameVersionDO, List<SonGameDto> sonGameList) {
		// 更新子游戏基础包
		List<GameVersionDO> gameVersionDOList = this.updateBasePack(parentGameVersionDO, sonGameList);

		// 更新对应主渠道测试包
		this.updateChlBasePack(parentGameVersionDO, sonGameList);

		return gameVersionDOList;
	}

	private void updateChlBasePack(ParentGameVersionDO parentGameVersionDO, List<SonGameDto> sonGameList) {
		if (CollectionUtils.isNotEmpty(sonGameList)) {
			sonGameList.forEach(sonGameDto -> updateChlBasePack(parentGameVersionDO, sonGameDto));
		}
	}


	private void updateChlBasePack(ParentGameVersionDO parentGameVersionDO, SonGameDto sonGameDto) {
		Long gameId = sonGameDto.getGameId();
		// 获取当前子游戏所有主渠道包
		List<String> chlCodeList = gameChannelPackService.getChlCodeByGameId(gameId);

		// 更新主渠道包
		WanGameVersionVO game = gameService.selectVersionVOByPK(gameId, parentGameVersionDO.getPackType());
		if (game == null || game.getVersionId() == null) {
			log.error("游戏基本包不存在");
			throw new BusinessException(11, "游戏基本包不存在");
		}
		GameChannelPackReq req = new GameChannelPackReq();
		req.setCreator(String.valueOf(SecurityUtils.getUser().getId()));
		req.setType(ChannelPackTypeEnum.DEFAULT.getType());
		Long versionId = game.getVersionId();
		GameVersionDO gameVersion = gameVersionService.getByPK(versionId);
		if (gameVersion == null) {
			log.error("版本基本包不存在");
			throw new BusinessException(12, "版本基本包不存在");
		}

		if (CollectionUtils.isNotEmpty(chlCodeList)) {
			for (String chlCode : chlCodeList) {
				ChannelManageVo channelVO = channelManageService.getVOByCode(chlCode);
				if (channelVO == null) {
					log.error("渠道不存在");
					continue;
				}
				List<String> packCodeList = new ArrayList<>();
				// 拼接  “渠道包编码”
				String packCode = chlCode + ChannelConstants.CHANNEL_PACK_SEP + gameId + ChannelConstants.CHANNEL_PACK_SEP + 1;
				packCodeList.add(packCode);
				gameChannelPackService.batchPackAsync(gameVersion, channelVO, packCodeList, req);
			}
		}
	}

	@Override
	public ParentGameVersionDO save(ParentGameVersionDO parentGameVersionDO) {
		Integer userId = SecurityUtils.getUser().getId();
		parentGameVersionDO.setCreator(String.valueOf(userId));
		parentGameVersionDO.setCreateTime(DateUtils.getCurrentDate());
		parentGameVersionDO.setStatus(VersionStatusEnum.VALID.getStatus());
		parentGameVersionDOMapper.insertSelective(parentGameVersionDO);

		// 将该父游戏历史母包置为失效
		this.disableOther(parentGameVersionDO.getGameId(), parentGameVersionDO.getVersionId(), parentGameVersionDO.getPackType());
		return parentGameVersionDO;
	}

	/**
	 * 将子游戏其它母包置为失效
	 *
	 * @param gameId
	 * @param versionId
	 */
	private void disableOther(Long gameId, Long versionId, Integer packType) {
		parentGameVersionDOMapper.disableOther(gameId, versionId, packType);
	}

	@Override
	public void deleteByPK(Long versionId) {
		ParentGameVersionDO parentGameVersionDO = new ParentGameVersionDO();
		parentGameVersionDO.setVersionId(versionId);
		parentGameVersionDO.setStatus(VersionStatusEnum.DELETE.getStatus());
		parentGameVersionDOMapper.updateByPrimaryKeySelective(parentGameVersionDO);
	}


}
